use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use crate::{vm::Value, PipitError};


/// 类型系统的核心枚举，表示所有可能的类型
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Type {
    Integer,
    Float,
    Boolean,
    String,
    Array(Box<Type>), // 数组元素类型
    Struct(String),   // 结构体名称
    Function(Vec<Type>, Box<Type>), // 参数类型列表和返回类型
    Instance(String), // 类实例，包含类名
    Class(String),    // 类定义
    NativeFunction,
    Null,
    Any,             // 任意类型
}

/// 类型环境，存储变量和函数的类型信息
pub struct TypeEnvironment {
    variables: RwLock<HashMap<String, Type>>,
    functions: RwLock<HashMap<String, Type>>,
    classes: RwLock<HashMap<String, ClassTypeInfo>>,
}

/// 类类型信息
#[derive(Clone)]
pub struct ClassTypeInfo {
    pub name: String,
    pub fields: HashMap<String, Type>,
    pub methods: HashMap<String, Type>,
}

impl TypeEnvironment {
    pub fn new() -> Self {
        TypeEnvironment {
            variables: RwLock::new(HashMap::new()),
            functions: RwLock::new(HashMap::new()),
            classes: RwLock::new(HashMap::new()),
        }
    }
    
    /// 添加变量类型
    pub fn add_variable(&self, name: String, type_: Type) {
        self.variables.write().unwrap().insert(name, type_);
    }
    
    /// 获取变量类型
    pub fn get_variable_type(&self, name: &str) -> Option<Type> {
        self.variables.read().unwrap().get(name).cloned()
    }
    
    /// 添加函数类型
    pub fn add_function(&self, name: String, type_: Type) {
        self.functions.write().unwrap().insert(name, type_);
    }
    
    /// 获取函数类型
    pub fn get_function_type(&self, name: &str) -> Option<Type> {
        self.functions.read().unwrap().get(name).cloned()
    }
    
    /// 添加类类型信息
    pub fn add_class(&self, info: ClassTypeInfo) {
        self.classes.write().unwrap().insert(info.name.clone(), info);
    }
    
    /// 获取类类型信息
    pub fn get_class_info(&self, name: &str) -> Option<ClassTypeInfo> {
        self.classes.read().unwrap().get(name).cloned()
    }
}

/// 类型检查器，用于静态类型分析
pub struct TypeChecker {
    env: Arc<TypeEnvironment>,
}

impl TypeChecker {
    pub fn new(env: Arc<TypeEnvironment>) -> Self {
        TypeChecker {
            env,
        }
    }
    
    /// 从运行时值推断类型
    pub fn infer_type_from_value(&self, value: &Value) -> Type {
        match value {
            Value::Integer(_) => Type::Integer,
            Value::Float(_) => Type::Float,
            Value::Boolean(_) => Type::Boolean,
            Value::String(_) => Type::String,
            Value::Array(_) => Type::Array(Box::new(Type::Any)), // 简化处理，实际应分析元素类型
            Value::Struct(_) => Type::Struct("Anonymous".to_string()), // 简化处理
            Value::Function(_) => Type::Function(vec![], Box::new(Type::Any)), // 简化处理
            Value::Instance(inst) => Type::Instance(inst.class_def.name.clone()),
            Value::Class(cls) => Type::Class(cls.name.clone()),
            Value::NativeFunction(_) => Type::NativeFunction,
            Value::CachedValue(val) => self.infer_type_from_value(&val),
            Value::Null => Type::Null,
            Value::Shared(_) => Type::Any,
        }
    }
    
    /// 检查两个类型是否兼容
    pub fn is_compatible(&self, expected: &Type, actual: &Type) -> bool {
        match (expected, actual) {
            (Type::Any, _) => true,
            (Type::Integer, Type::Float) => true, // 允许整数隐式转换为浮点数
            (Type::Float, Type::Integer) => true, // 允许浮点数隐式转换为整数
            (Type::String, Type::Integer) => true, // 允许整数转换为字符串
            (Type::String, Type::Float) => true,  // 允许浮点数转换为字符串
            (Type::String, Type::Boolean) => true, // 允许布尔值转换为字符串
            (Type::Boolean, Type::Integer) => true, // 允许整数转换为布尔值
            (t1, t2) if t1 == t2 => true,
            (Type::Array(elem1), Type::Array(elem2)) => self.is_compatible(&elem1, &elem2),
            (Type::Instance(cls1), Type::Instance(cls2)) => cls1 == cls2,
            _ => false,
        }
    }
    
    /// 尝试将一个值转换为目标类型
    pub fn try_coerce_value(&self, value: Value, target_type: &Type) -> crate::error::Result<Value> {
        match (value, target_type) {
            // 整数转换
            (Value::Integer(i), Type::Float) => Ok(Value::Float(i as f64)),
            (Value::Integer(i), Type::String) => Ok(Value::String(i.to_string())),
            (Value::Integer(i), Type::Boolean) => Ok(Value::Boolean(i != 0)),
            
            // 浮点数转换
            (Value::Float(f), Type::Integer) => Ok(Value::Integer(f as i32)),
            (Value::Float(f), Type::String) => Ok(Value::String(f.to_string())),
            (Value::Float(f), Type::Boolean) => Ok(Value::Boolean(f != 0.0)),
            
            // 布尔值转换
            (Value::Boolean(b), Type::Integer) => Ok(Value::Integer(if b { 1 } else { 0 })),
            (Value::Boolean(b), Type::Float) => Ok(Value::Float(if b { 1.0 } else { 0.0 })),
            (Value::Boolean(b), Type::String) => Ok(Value::String(b.to_string())),
            
            // 字符串转换
            (Value::String(s), Type::Integer) => {
                match s.parse::<i32>() {
                    Ok(i) => Ok(Value::Integer(i)),
                    Err(_) => Err(PipitError::TypeError(format!("Cannot convert string '{}' to integer", s)))
                }
            },
            (Value::String(s), Type::Float) => {
                match s.parse::<f64>() {
                    Ok(f) => Ok(Value::Float(f)),
                    Err(_) => Err(PipitError::TypeError(format!("Cannot convert string '{}' to float", s)))
                }
            },
            (Value::String(s), Type::Boolean) => {
                match s.to_lowercase().as_str() {
                    "true" | "yes" | "1" => Ok(Value::Boolean(true)),
                    "false" | "no" | "0" => Ok(Value::Boolean(false)),
                    _ => Err(PipitError::TypeError(format!("Cannot convert string '{}' to boolean", s)))
                }
            },
            
            // 数组转换
            (Value::Array(arr), Type::String) => {
                let elements: Vec<String> = arr.iter()
                    .map(|v| match v {
                        Value::String(s) => s.clone(),
                        v => self.try_coerce_value(v.clone(), &Type::String)
                            .map(|s| match s { Value::String(s) => s, _ => "".to_string() })
                            .unwrap_or("".to_string())
                    })
                    .collect();
                Ok(Value::String(format!("[{}]", elements.join(", "))))
            },
            
            // 类型相同，无需转换
            (v, t) if self.is_compatible(&self.infer_type_from_value(&v), t) => Ok(v),
            
            // 无法转换
            (v, t) => Err(PipitError::TypeError(format!(
                "Cannot convert value of type {:?} to {:?}", 
                self.infer_type_from_value(&v), t
            )))
        }
    }
    
    /// 获取函数签名的兼容性
    pub fn check_function_compatibility(&self, expected: &Type, actual: &Type) -> bool {
        match (expected, actual) {
            (Type::Function(exp_params, exp_ret), Type::Function(act_params, act_ret)) => {
                if exp_params.len() != act_params.len() {
                    return false;
                }
                
                // 检查每个参数类型是否兼容
                for (exp_param, act_param) in exp_params.iter().zip(act_params.iter()) {
                    if !self.is_compatible(exp_param, act_param) {
                        return false;
                    }
                }
                
                // 检查返回类型是否兼容
                self.is_compatible(exp_ret, act_ret)
            },
            _ => false,
        }
    }
    
    /// 获取数组的元素类型（用于类型推断优化）
    pub fn get_array_element_type(&self, array: &Value) -> Option<Type> {
        match array {
            Value::Array(elements) => {
                if elements.is_empty() {
                    Some(Type::Any)
                } else {
                    // 尝试推断数组元素的公共类型
                    let first_type = self.infer_type_from_value(&elements[0]);
                    let all_same_type = elements.iter()
                        .all(|elem| self.is_compatible(&first_type, &self.infer_type_from_value(elem)));
                    
                    if all_same_type {
                        Some(first_type)
                    } else {
                        Some(Type::Any)
                    }
                }
            },
            _ => None
        }
    }
}

/// 类型系统的全局实例
pub struct TypeSystem {
    env: Arc<TypeEnvironment>,
    checker: TypeChecker,
}

impl TypeSystem {
    pub fn new() -> Self {
        let env = Arc::new(TypeEnvironment::new());
        let checker = TypeChecker::new(env.clone());
        
        TypeSystem {
            env,
            checker,
        }
    }
    
    /// 获取类型环境
    pub fn get_environment(&self) -> Arc<TypeEnvironment> {
        self.env.clone()
    }
    
    /// 获取类型检查器
    pub fn get_checker(&self) -> &TypeChecker {
        &self.checker
    }
    
    /// 注册内置类型
    pub fn register_builtin_types(&self) {
        // 注册一些常用的函数类型
        // 例如：二元操作函数 (Int, Int) -> Int
        let int_binary_op = Type::Function(
            vec![Type::Integer, Type::Integer],
            Box::new(Type::Integer)
        );
        self.env.add_function("add".to_string(), int_binary_op.clone());
        self.env.add_function("subtract".to_string(), int_binary_op.clone());
        self.env.add_function("multiply".to_string(), int_binary_op.clone());
        self.env.add_function("divide".to_string(), int_binary_op);
        
        // 浮点数二元操作函数
        let float_binary_op = Type::Function(
            vec![Type::Float, Type::Float],
            Box::new(Type::Float)
        );
        self.env.add_function("fadd".to_string(), float_binary_op.clone());
        self.env.add_function("fsub".to_string(), float_binary_op.clone());
        self.env.add_function("fmul".to_string(), float_binary_op.clone());
        self.env.add_function("fdiv".to_string(), float_binary_op);
    }
}

/// 类型特化辅助函数，用于高级优化
pub fn create_specialized_type_signature(
    param_types: Vec<Type>,
    return_type: Type
) -> Type {
    Type::Function(param_types, Box::new(return_type))
}

/// 将ValueKind转换为Type
pub fn value_kind_to_type(kind: &crate::advanced_optimizations::ValueKind) -> Type {
    match kind {
        crate::advanced_optimizations::ValueKind::Integer => Type::Integer,
        crate::advanced_optimizations::ValueKind::Float => Type::Float,
        crate::advanced_optimizations::ValueKind::Boolean => Type::Boolean,
        crate::advanced_optimizations::ValueKind::String => Type::String,
        crate::advanced_optimizations::ValueKind::Array => Type::Array(Box::new(Type::Any)),
        crate::advanced_optimizations::ValueKind::Struct => Type::Struct("Anonymous".to_string()),
        crate::advanced_optimizations::ValueKind::Function => Type::Function(vec![], Box::new(Type::Any)),
        crate::advanced_optimizations::ValueKind::Instance => Type::Instance("Unknown".to_string()),
        crate::advanced_optimizations::ValueKind::Class => Type::Class("Unknown".to_string()),
        crate::advanced_optimizations::ValueKind::NativeFunction => Type::NativeFunction,
        crate::advanced_optimizations::ValueKind::CachedValue => Type::Any,
        crate::advanced_optimizations::ValueKind::Shared => Type::Any,
        crate::advanced_optimizations::ValueKind::Other => Type::Any,
    }
}